/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package main;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Simply
 */
public class Driver {

    private static List<String> parseArgSet(String s) {
        List<String> values = new ArrayList<>();
        s = s.trim();
        if (s.startsWith("{") && s.endsWith("}")) {
            s = s.substring(1, s.length() - 1);
            for (String token : s.split(",")) {
                values.add(token.trim());
            }
        } else {
            values.add(s.trim());
        }
        return values;
    }
    
    private static Map<String, List<String>> parseArgs(String[] args) {
        Map<String, List<String>> params = new HashMap<>();
        /* args[0] es el nombre de la clase, args[1] el del fichero de datos */
        for (int i = 2; i < args.length; i += 2) {
            params.put(args[i], parseArgSet(args[i+1]));
        }
        
        return params;
    }
    
    private static String className(String[] args) {
        return args[0].trim();
    }
    
    private static List<List<String>> generateArgumentLists(Map<String, List<String>> parameters) {
        List<List<String>> values = new LinkedList<>();
        values.add(new ArrayList<String>());
        for (Entry<String, List<String>> parameter : parameters.entrySet()) {
            List<List<String>> newValues = new LinkedList<>();
            String parameterName = parameter.getKey();
            
            for (String parameterValue : parameter.getValue()) {
                for (List<String> previousEntry : values) {
                    List<String> newEntry = new ArrayList(previousEntry);
                    newEntry.add(parameterName);
                    newEntry.add(parameterValue);
                    newValues.add(newEntry);
                }
            }
            values = newValues;
        }

        return values;
    }

    private static String fileNameForArgs(String base, List<String> args) {
        String result = base;
        for (String arg : args) {
            base = base + "_" + arg;
        }
        base = base + ".log";
        return base;
    }
    
    public static void main(String[] args) {
        try {
            Class c = Class.forName(className(args));
            Method main = c.getMethod("main", String[].class);
            Map<String, List<String>> parameters = parseArgs(args);
            
            List<List<String>> argumentLists = generateArgumentLists(parameters);
            
            for (List<String> argumentList : argumentLists) {
                argumentList.add(0, fileNameForArgs(args[1], argumentList));
                argumentList.add(0, "-log");
                argumentList.add(0, args[1]);                
                String[] invocationArgs = argumentList.toArray(new String[0]);
                System.out.println("Running " + c + " with args " + Arrays.toString(invocationArgs));
                main.invoke(null, (Object)invocationArgs);
            }
            
        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException 
                | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            Logger.getLogger(Driver.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
}
